﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.Reflection;
using System.IO;
using System.Runtime.Serialization;
using System.Security.Cryptography;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Configuration;
using System.Web.Script.Serialization;
//
//using NHTC.DataAccess;

public delegate void SubInvoker(object sInput);
public delegate object FunctionInvoker(object sInput);
public delegate void FormatInvoker(string sFieldName, ref object sValue);

public static class Globals
{
    public const string vbCr = "\r";
    public const string vbLf = "\n";
    public const string vbCrLf = "\r\n"; //System.NewLine
    public const string vbTab = "\t";
    //

    public static string CS_MONEY_FORMAT = "#,##0";
    public static string CS_DISPLAY_RATE_FORMAT = "0.#####";//;"#0.0#";
    public static string CS_DISPLAY_MONTHYEAR_FORMAT = "MM/yyyy";
    public static string CS_DISPLAY_DATE_FORMAT = "dd/MM/yyyy";
    public static string CS_DISPLAY_TIME_FORMAT = "HH:mm";
    public static string CS_DISPLAY_DATETIME_FORMAT = "dd-MMM-yyyy HH:mm";
    public static string CS_DISPLAY_TIMEDATE_FORMAT = "HH:mm dd-MMM-yyyy";
    public static string CS_DISPLAY_NUMBER_FORMAT = "#,##0";
    public static string CS_DISPLAY_NUMBER_WITHOUT_FORMAT = "";
    public static string CS_EDIT_MONTHYEAR_FORMAT = "MM/yyyy";
    public static string CS_EDIT_DATE_FORMAT = "dd/MM/yyyy";
    public static string CS_EDIT_DATETIME_FORMAT = "dd/MM/yyyy HH:mm";
    public static string CS_EDIT_TIME_FORMAT = "HH:mm";
    public static string CS_DECIMAL_SYMBOL = ".";
    public static string CS_DIGIT_GROUP_SYMBOL = ",";
    //
    public static string Application_GetConfig(string sSectionKey, bool bEncode)
    {
        string sValue = Application_GetConfig(sSectionKey);
        if (bEncode)
        {
            Assembly m_MyAssembly = Assembly.GetCallingAssembly();
            string sGUID = m_MyAssembly.GetType().GUID.ToString();
            sValue = String_Decrypt(sValue, Application_GetID(sGUID));
        }
        return sValue;
    }

    public static string Application_GetConfig(string sSectionKey)
    {
        string sValue = "";
        if (ConfigurationManager.AppSettings.AllKeys.Contains(sSectionKey))
        {
            sValue = ConfigurationManager.AppSettings[sSectionKey].ToString();
        }
        return sValue;
    }

    public static void Application_SetConfig(string sSectionKey, string sValue, bool bEncode)
    {
        if (bEncode)
        {
            Assembly m_MyAssembly = Assembly.GetCallingAssembly();
            string sGUID = m_MyAssembly.GetType().GUID.ToString();
            sValue = String_Encrypt(sValue, Application_GetID(sGUID));
        }
        Application_SetConfig(sSectionKey, sValue);
    }

    public static void Application_SetConfig(string sSectionKey, string sValue)
    {
        System.Configuration.Configuration config = default(System.Configuration.Configuration);

        //Dùng config chạy trên windows
        if (System.Web.HttpRuntime.AppDomainAppId == null)
        {
            config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
        }
        else
        {
            config = WebConfigurationManager.OpenWebConfiguration("~");
        }


        // Add an Application Setting.
        if (Array.IndexOf(config.AppSettings.Settings.AllKeys, sSectionKey) >= 0)
        {
            config.AppSettings.Settings[sSectionKey].Value = sValue;
        }
        else
        {
            config.AppSettings.Settings.Add(sSectionKey, sValue);
        }
        // Save the configuration file.
        config.Save(ConfigurationSaveMode.Modified);
        // Force a reload of a changed section.
        ConfigurationManager.RefreshSection("appSettings");
    }

    public static string Application_GetDesc()
    {
        Assembly m_MyAssembly = Assembly.GetEntryAssembly();
        if (m_MyAssembly.IsDefined(typeof(AssemblyDescriptionAttribute), true))
        {
            Attribute attr = Attribute.GetCustomAttribute(m_MyAssembly, typeof(AssemblyDescriptionAttribute));
            AssemblyDescriptionAttribute title_attr = (AssemblyDescriptionAttribute)attr;
            return title_attr.Description;
        }
        else
        {
            return "";
        }
    }

    public static string Application_GetTitle()
    {
        Assembly m_MyAssembly = Assembly.GetEntryAssembly();
        if (m_MyAssembly!=null && m_MyAssembly.IsDefined(typeof(AssemblyTitleAttribute), true))
        {
            Attribute attr = Attribute.GetCustomAttribute(m_MyAssembly, typeof(AssemblyTitleAttribute));
            AssemblyTitleAttribute title_attr = (AssemblyTitleAttribute)attr;
            return title_attr.Title;
        }
        else
        {
            return "";
        }
    }

    public static string Application_GetVersion()
    {
        Assembly m_MyAssembly = Assembly.GetEntryAssembly();
        FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(m_MyAssembly.Location);
        return fvi.FileVersion;
    }

    public static string Application_GetPath()
    {
        Assembly m_MyAssembly = Assembly.GetEntryAssembly();
        string sPath = m_MyAssembly.Location;
        return sPath.Substring(0, sPath.LastIndexOf("\\"));
    }

    private static string Application_GetID(string sGUID)
    {
        //Dim sGUID As String = m_MyAssembly.GetType().GUID.ToString()
        decimal retVal = 0;
        foreach (string sHex in sGUID.Split('-'))
        {
            retVal += long.Parse(sHex, System.Globalization.NumberStyles.HexNumber);
        }
        return retVal.ToString();
    }

    public static string Application_GetID()
    {
        Assembly m_MyAssembly = Assembly.GetEntryAssembly();
        string sGUID = m_MyAssembly.GetType().GUID.ToString();
        return Application_GetID(sGUID);
    }

    public static void Application_SetCultureInfo(System.Threading.Thread mThread)
    {
        //Set khuôn dạng Date và Number cho 1 thread
        System.Globalization.DateTimeFormatInfo myDateformat = new System.Globalization.DateTimeFormatInfo();
        myDateformat.ShortDatePattern = CS_DISPLAY_DATE_FORMAT;
        myDateformat.FullDateTimePattern = CS_DISPLAY_DATETIME_FORMAT;
        //Set upper case for abb month name
        string[] arrMonthName = myDateformat.AbbreviatedMonthNames;
        for (int i = 0; i <= arrMonthName.Length - 1; i++)
        {
            arrMonthName[i] = arrMonthName[i].ToUpper();
        }
        myDateformat.AbbreviatedMonthNames = arrMonthName;
        //
        System.Globalization.NumberFormatInfo myNumberformat = new System.Globalization.NumberFormatInfo();
        myNumberformat.NumberDecimalSeparator = CS_DECIMAL_SYMBOL;
        myNumberformat.CurrencyDecimalSeparator = myNumberformat.NumberDecimalSeparator;
        myNumberformat.NumberGroupSeparator = CS_DIGIT_GROUP_SYMBOL;
        myNumberformat.CurrencyGroupSeparator = myNumberformat.NumberGroupSeparator;
        //
        mThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
        mThread.CurrentCulture.DateTimeFormat = myDateformat;
        mThread.CurrentCulture.NumberFormat = myNumberformat;
    }

    public static bool ConnectString_IsSql(string cn)
    {
        cn = cn.ToUpper();
        bool RV = true;
        try
        {
            if (cn.Contains("ATTACHDBFILENAME"))
            {
                //-split dau ; de phan tich, xet connect toi sql
                RV = true;
            }
            else
            {
                if (!cn.Contains("DATA SOURCE"))
                {
                    throw new MissingMemberException("Missing Data Source");
                }
                if (!cn.Contains("INITIAL CATALOG"))
                {
                    throw new MissingMemberException("Missing Initial Catalog");
                }
                if (!cn.Contains("USER ID"))
                {
                    throw new MissingMemberException("Missing User ID");
                }
                if (!cn.Contains("PASSWORD"))
                {
                    throw new MissingMemberException("Missing Password");
                }
                string[] contents = cn.Split(char.Parse(";"));
                if (!contents[0].StartsWith("DATA SOURCE"))
                {
                    throw new MissingMemberException("Missing Data Source");
                }
                if (!contents[1].StartsWith("INITIAL CATALOG"))
                {
                    throw new MissingMemberException("Missing Initial Catalog");
                }
                if (!contents[2].StartsWith("USER ID"))
                {
                    throw new MissingMemberException("Missing User ID");
                }
                if (!contents[3].StartsWith("PASSWORD"))
                {
                    throw new MissingMemberException("Missing Password");
                }
            }
        }
        catch (Exception)
        {
            RV = false;
        }
        return RV;
    }

    public static string ArrayToString(object[] arrObject)
    {
        return ArrayToString(arrObject, ",");
    }

    public static string ArrayToString(object[] arrObject, string seperator)
    {
        string retVal = "";
        foreach (object obj in arrObject)
        {
            if (retVal.Length > 0)
                retVal += seperator;
            retVal += obj.ToString();
        }
        return retVal;
    }

    public static object DB_GetNull(object objField)
    {
        return Null.GetNull(objField, DBNull.Value);
    }

    public static object DB_GetNull(object objField, object objNull)
    {
        return Null.GetNull(objField, objNull);
    }

    public static object DB_GetValue(object objField, object objDefault = null)
    {
        if (object.ReferenceEquals(objField, DBNull.Value) || objField == null)
        {
            return objDefault;
        }
        else
        {
            return objField;
        }
    }

    public static T DB_GetValue<T>(object objField, T objDefault)
    {
        if (object.ReferenceEquals(objField, DBNull.Value) || objField == null)
        {
            return objDefault;
        }
        else
        {
           return (T)Convert.ChangeType(objField,typeof(T));
        }
    }

    public static T DB_GetValue<T>(object objField)
    {
        T objDefault = default(T);
        if (object.ReferenceEquals(objField, DBNull.Value) || objField == null)
        {
            if (objDefault == null)
            {
                return (T)Null.SetNullValue("");
            }
            else
            {
                return (T)Null.SetNullValue(objDefault);
            }
        }
        else
        {
            return (T)objField;
        }
    }

    public static bool DB_CheckValue(object objField)
    {
        if (object.ReferenceEquals(objField, DBNull.Value) || objField == null)
        {
            return false;
        }
        else
        {
            if (objField is string)
            {
                return !string.IsNullOrEmpty((string)objField);
            }
            else
            {
                return true;
            }
        }
    }

    public static string DB_GetString(object objField)
    {
        return DB_GetString(objField, "");
    }

    public static string DB_GetString(object objField, string strDefault)
    {
        if (object.ReferenceEquals(objField, DBNull.Value) || objField == null)
        {
            return strDefault;
        }
        else
        {
            if (objField is System.DateTime)
            {
                return ((System.DateTime)objField).ToString(CS_DISPLAY_DATE_FORMAT);
            }
            else if ((objField != null))
            {
                if (objField.GetType().IsValueType && objField.GetType() != typeof(Boolean))
                {
                    return String.Format("##0.##", objField);
                }
                else
                {
                    return objField.ToString();
                }
            }
            else
            {
                return "";
            }
        }
    }

    public static string String_Repeat(string sChar, int iCount)
    {
        //Lap lai ky tu n lan
        string sReturn = "";
        if (sChar.Length == 1)
        {
            sReturn = sReturn.PadRight(iCount, sChar[0]);
        }
        else
        {
            for (int i = 1; i <= iCount; i++)
            {
                sReturn += sChar;
            }
        }
        return sReturn;
    }

    public static bool String_IsAlphaNumeric(string sText)
    {
        //Ham kiem tra chuoi co bao gom ca chu va so hay khong
        //thuong dung de kiem tra khi khoi tao mat khau
        return Regex.IsMatch(sText, "^(?=.*\\d)(?=.*[a-zA-Z])");
    }

    public static string String_StripDiacritics(string sText)
    {
        //Lay chuoi ky tu khong dau
        System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex("\\p{IsCombiningDiacriticalMarks}+");
        //
        string strFormD = sText.Normalize(System.Text.NormalizationForm.FormD);
        return regex.Replace(strFormD, string.Empty).Replace((char)0x111, 'd').Replace((char)0x110, 'D').Replace((char)0xd0, 'D');
    }

    public static string String_Number(decimal numValue)
    {
        string sDecChar = System.Threading.Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator;
        string retVal = numValue.ToString();
        retVal = retVal.Replace(sDecChar, ".");
        return retVal;
    }

    public static string String_ClearInjection(string input)
    {
        if (string.IsNullOrEmpty(input))
        {
            return "";
        }
        else if (input.Contains(";") && (input.Contains("--") || input.Contains("/*") || input.ToUpper().Contains("DECLARE")))
        {
            return "";
        }
        else
        {
            return input.Replace("'", "''");
        }
    }

    public static void String_ConditionAppend(ref string condition, string input)
    {
        String_ConditionAppend(ref condition, input, "AND");
    }

    public static void String_ConditionAppend(ref string condition, string input, string sConnector)
    {
        if (string.IsNullOrEmpty(input))
            return;
        if (string.IsNullOrEmpty(condition))
        {
            condition = input;
        }
        else
        {
            condition += " " + sConnector + " " + input;
        }
    }

    public static string String_ParseFullText(string searchText, bool bMatchAll)
    {
        if (string.IsNullOrEmpty(searchText))
            return "";
        List<string> lstKeyword = String_ParseKeywords(searchText);
        string sTemp = "";
        string sWord2 = "";
        if ((lstKeyword != null))
        {
            foreach (string sWord in lstKeyword)
            {
                sWord2 = sWord;
                if (sWord.Contains(" "))
                    sWord2 = "\"" + sWord + "\"";
                if (sTemp.Length == 0)
                {
                    sTemp = sWord2;
                }
                else
                {
                    if (bMatchAll)
                    {
                        sTemp += " AND " + sWord2;
                    }
                    else
                    {
                        sTemp += " OR " + sWord2;
                    }
                }
            }
        }
        return sTemp;
    }

    public static string String_ParseLike(string fieldName, string searchText, bool bMatchAll)
    {
        List<string> lstKeyword = String_ParseKeywords(searchText);
        string retVal = "";
        string sWord = "";
        if ((lstKeyword != null))
        {
            foreach (string sTemp in lstKeyword)
            {
                sWord = sTemp.Trim();
                if (sWord.Contains("*"))
                {
                    sWord = sWord.Replace("*", "%");
                }
                if (retVal.Length > 0)
                {
                    if (bMatchAll)
                    {
                        retVal += " AND ";
                    }
                    else
                    {
                        retVal += " OR ";
                    }
                }
                retVal += "(";
                retVal += fieldName + " LIKE N'% " + sWord + " %'";
                retVal += " OR ";
                retVal += fieldName + " LIKE N'" + sWord + " %'";
                retVal += " OR ";
                retVal += fieldName + " LIKE N'% " + sWord + "'";
                retVal += ")";
            }
        }
        return retVal;
    }

    public static List<string> String_ParseKeywords(string sText)
    {
        if (string.IsNullOrEmpty(sText))
        {
            return null;
        }
        sText = sText.Trim();
        sText = sText.Replace(",", "");
        sText = sText.Replace(".", "");
        List<string> lstKeyword = new List<string>();
        int iPos = sText.IndexOf("\"");
        string sKeyword = null;
        if (iPos == -1)
        {
            lstKeyword.AddRange(sText.Split(' '));
        }
        else
        {
            while (iPos > -1)
            {
                if (iPos > 0)
                {
                    sKeyword = sText.Substring(0, iPos).Trim();
                    lstKeyword.AddRange(sKeyword.Split(' '));
                    sText = sText.Substring(iPos).Trim();
                }
                else
                {
                    iPos = sText.IndexOf("\"", iPos + 1);
                    if (iPos > 0)
                    {
                        sKeyword = sText.Substring(1, iPos - 1);
                        lstKeyword.Add(sKeyword);
                        if (iPos + 1 == sText.Length)
                        {
                            break; // TODO: might not be correct. Was : Exit Do
                        }
                        sText = sText.Substring(iPos + 1).Trim();
                    }
                    else
                    {
                        break; // TODO: might not be correct. Was : Exit Do
                    }
                }
                iPos = sText.IndexOf("\"");
                if (iPos == -1)
                {
                    lstKeyword.AddRange(sText.Split(' '));
                    break; // TODO: might not be correct. Was : Exit Do
                }
            }
        }
        return lstKeyword;
    }

    /// <summary>
    /// method for determining is the user provided a valid email address
    /// We use regular expressions in this check, as it is a more thorough
    /// way of checking the address provided
    /// </summary>
    /// <param name="email">email address to validate</param>
    /// <returns>true is valid, false if not valid</returns>
    public static bool String_IsValidEmail(string email)
    {
        //regular expression pattern for valid email
        //addresses, allows for the following domains:
        //com,edu,info,gov,int,mil,net,org,biz,name,museum,coop,aero,pro,tv
        string pattern = "[a-zA-Z0-9_-]+(?:\\.[A-Za-z0-9_-]+)*@[-.a-zA-Z0-9]+(\\.[-.a-zA-Z0-9]+)*\\." + "(com|edu|info|gov|int|mil|net|org|biz|name|museum|coop|aero|pro|tv|[a-zA-Z]{2})$";
        //Dim pattern As String = "^[-a-zA-Z0-9][-.a-zA-Z0-9]*@[-.a-zA-Z0-9]+(\.[-.a-zA-Z0-9]+)*\." & _
        //"(com|edu|info|gov|int|mil|net|org|biz|name|museum|coop|aero|pro|tv|[a-zA-Z]{2})$"
        //Regular expression object
        Regex check = new Regex(pattern, RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase);
        //boolean variable to return to calling method
        bool valid = false;

        //make sure an email address was provided
        if (string.IsNullOrEmpty(email))
        {
            valid = false;
        }
        else
        {
            //use IsMatch to validate the address
            valid = check.IsMatch(email);
        }
        //return the value to the calling method
        return valid;
    }

    public static bool String_IsValidWeb(string address)
    {
        return Regex.IsMatch(address, "http(s)?://([\\w-]+\\.)+[\\w-]+(/[\\w- ./?%&=]*)?");
    }

    public static string String_Encrypt(string strText, string strEncrKey)
    {
        try
        {
            strEncrKey = (strEncrKey + String_Repeat("0", IV.Length)).Substring(0, IV.Length);
            byte[] bykey = System.Text.Encoding.UTF8.GetBytes(strEncrKey);
            byte[] InputByteArray = System.Text.Encoding.UTF8.GetBytes(strText);
            RijndaelManaged des = new RijndaelManaged();
            des.KeySize = IV.Length * 8;
            MemoryStream ms = new MemoryStream();
            CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(bykey, IV), CryptoStreamMode.Write);

            cs.Write(InputByteArray, 0, InputByteArray.Length);
            cs.FlushFinalBlock();

            string retVal = Convert.ToBase64String(ms.ToArray());
            return retVal;
        }
        catch (Exception ex)
        {
            return ex.Message;
        }
    }

    public static string String_Decrypt(string strText, string sDecrKey)
    {
        byte[] inputByteArray = new byte[strText.Length + 1];
        try
        {
            sDecrKey = (sDecrKey + String_Repeat("0", IV.Length)).Substring(0, IV.Length);
            byte[] byKey = System.Text.Encoding.UTF8.GetBytes(sDecrKey);
            RijndaelManaged des = new RijndaelManaged();
            des.KeySize = IV.Length * 8;
            inputByteArray = Convert.FromBase64String(strText);
            MemoryStream ms = new MemoryStream();
            CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(byKey, IV), CryptoStreamMode.Write);

            cs.Write(inputByteArray, 0, inputByteArray.Length);
            cs.FlushFinalBlock();
            System.Text.Encoding encoding = System.Text.Encoding.UTF8;

            return encoding.GetString(ms.ToArray());
        }
        catch (Exception ex)
        {
            return ex.Message;
        }
    }

    public static byte[] ByteArray_Encrypt(byte[] InputByteArray, string strEncrKey)
    {
        try
        {
            strEncrKey = (strEncrKey + String_Repeat("0", IV.Length)).Substring(0, IV.Length);
            byte[] bykey = System.Text.Encoding.UTF8.GetBytes(strEncrKey);
            RijndaelManaged des = new RijndaelManaged();
            des.KeySize = IV.Length * 8;
            MemoryStream ms = new MemoryStream();
            CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(bykey, IV), CryptoStreamMode.Write);

            cs.Write(InputByteArray, 0, InputByteArray.Length);
            cs.FlushFinalBlock();

            return ms.ToArray();
        }
        catch
        {
            return null;
        }
    }

    private static byte[] IV = {
		0xab,
		0xcd,
		0xef,
		0x12,
		0x34,
		0x56,
		0x78,
		0x90,
		0x13,
		0x24,
		0x57,
		0x68,
		0x9a,
		0xbd,
		0xce,
		0xdf

	};
    

    public static byte[] ByteArray_Decrypt(byte[] inputByteArray, string sDecrKey)
    {
        try
        {
            sDecrKey = (sDecrKey + String_Repeat("0", IV.Length)).Substring(0, IV.Length);
            byte[] byKey = System.Text.Encoding.UTF8.GetBytes(sDecrKey);
            RijndaelManaged des = new RijndaelManaged();
            des.KeySize = IV.Length * 8;
            MemoryStream ms = new MemoryStream();
            CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(byKey, IV), CryptoStreamMode.Write);

            cs.Write(inputByteArray, 0, inputByteArray.Length);
            cs.FlushFinalBlock();

            return ms.ToArray();
        }
        catch
        {
            return null;
        }
    }

    //Public Function RSA_Encrypt(ByVal DataToEncrypt() As Byte) As Byte()
    //    Try
    //        RSA_ValidateKeys()
    //        '
    //        Dim encryptedData() As Byte
    //        Using RSA As New RSACryptoServiceProvider(2048)               
    //            RSA.FromXmlString(IO.File.ReadAllText(RSA_KEY_PUBLIC))
    //            encryptedData = RSA.Encrypt(DataToEncrypt, True)
    //        End Using
    //        Return encryptedData
    //        'Catch and display a CryptographicException   
    //        'to the console. 
    //    Catch e As CryptographicException
    //        Return Nothing
    //    End Try
    //End Function

    //Private RSA_KEY_PUBLIC As String = "Lib\public.key"
    //Private RSA_KEY_PRIVATE As String = "Lib\private.key"
    //Private Sub RSA_ValidateKeys()
    //    If Not Web.HttpRuntime.AppDomainAppId Is Nothing AndAlso Not RSA_KEY_PRIVATE.Contains(Web.HttpRuntime.AppDomainAppPath) Then
    //        RSA_KEY_PRIVATE = Web.HttpRuntime.AppDomainAppPath + "bin\" + RSA_KEY_PRIVATE
    //        RSA_KEY_PUBLIC = Web.HttpRuntime.AppDomainAppPath + "bin\" + RSA_KEY_PUBLIC
    //    End If
    //    If Not File.Exists(RSA_KEY_PRIVATE) AndAlso Not File.Exists(RSA_KEY_PUBLIC) Then
    //        Dim key As RSA = RSA.Create
    //        key.KeySize = 2048
    //        Dim privateKey As String = key.ToXmlString(True)
    //        Dim publicKey As String = key.ToXmlString(False)
    //        Dim privateFile As StreamWriter = File.CreateText(RSA_KEY_PRIVATE)
    //        privateFile.Write(privateKey)
    //        privateFile.Close()
    //        privateFile.Dispose()
    //        Dim publicFile As StreamWriter = File.CreateText(RSA_KEY_PUBLIC)
    //        publicFile.Write(publicKey)
    //        publicFile.Close()
    //        publicFile.Dispose()
    //    End If
    //End Sub

    //Public Function RSA_Decrypt(ByVal DataToDecrypt() As Byte) As Byte()
    //    Try
    //        RSA_ValidateKeys()
    //        '
    //        Dim decryptedData() As Byte
    //        'Create a new instance of RSACryptoServiceProvider. 
    //        Using RSA As New RSACryptoServiceProvider(2048)
    //            'Import the RSA Key information. This needs 
    //            'to include the private key information.
    //            RSA.FromXmlString(File.ReadAllText(RSA_KEY_PRIVATE))
    //            'Decrypt the passed byte array and specify OAEP padding.   
    //            'OAEP padding is only available on Microsoft Windows XP or 
    //            'later.  
    //            decryptedData = RSA.Decrypt(DataToDecrypt, True)
    //            'Catch and display a CryptographicException   
    //            'to the console. 
    //        End Using
    //        Return decryptedData
    //    Catch e As CryptographicException
    //        Return Nothing
    //    End Try
    //End Function

    public static string String_Hash(string input)
    {
        // Create a new instance of the MD5 object.
        System.Security.Cryptography.MD5 md5Hasher = System.Security.Cryptography.MD5.Create();

        // Convert the input string to a byte array and compute the hash.
        byte[] data = md5Hasher.ComputeHash(System.Text.Encoding.Default.GetBytes(input));

        // Create a new Stringbuilder to collect the bytes
        // and create a string.
        StringBuilder sBuilder = new StringBuilder();

        // Loop through each byte of the hashed data 
        // and format each one as a hexadecimal string.
        int i = 0;
        for (i = 0; i <= data.Length - 1; i++)
        {
            sBuilder.Append(data[i].ToString("x2"));
        }

        // Return the hexadecimal string.
        return sBuilder.ToString();
    }

    public static bool String_IsBase64(string sValue)
    {
        return Regex.IsMatch(sValue, "^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$");
    }

    public static string String_Random(int iLen)
    {
        //Dung cac ky tu chu:
        //   0-9: 48-57 map 0-9
        //   A-Z: 65-90 map 10-35
        //   a-z: 97-122 map 36-61

        string sRet = "";
        string iASCII = "";
        Random r = new Random();

        for (int i = 1; i <= iLen; i++)
        {
            //Lay random 1 so thu tu
            //Chi dung chu hoa nen lay random trong 35
            int iIndex = r.Next(0, 35);
            //Lay ra ascii tuong ung cua ky tu tuong ung voi so thu tu theo map o phan dau

            if (iIndex < 10)
                iIndex += 48;
            else if (iIndex < 36)
                iIndex += 55;
            else iIndex += 61;

            //Lay ra ky tu ASCII tuong ung
            sRet += Encoding.ASCII.GetBytes(iIndex.ToString()).ToString();
        }

        r = null;

        return sRet;
    }

    public static string String_Date2Text(DateTime dateValue)
    {
        string retVal = null;
        retVal = "Ngày " + (dateValue.Day <= 10 ? "mùng " : "") + String_Num2Text(dateValue.Day.ToString(), false) + ", tháng " + String_Num2Text(dateValue.Month.ToString(), false) + ", năm " + String_Num2Text(dateValue.Year.ToString(), false);
        return retVal;
    }

    public static string String_SqlDate(string sValue)
    {
        return String_SqlDate(Object_SetValueEx<System.DateTime>(sValue));
    }

    public static string String_SqlDate(System.DateTime dtValue)
    {
        if (dtValue.Year > 1900)
        {
            return "CONVERT(DATETIME,'" + dtValue.ToString("dd/MM/yyyy") + "',103)";
        }
        else
        {
            return "";
        }
    }

    public static string String_OracleDate(string sValue)
    {
        return String_OracleDate(Object_SetValueEx<System.DateTime>(sValue));
    }

    public static string String_OracleDate(System.DateTime dtValue)
    {
        if (dtValue.Year > 1900)
        {
            return "TO_DATE('" + dtValue.ToString("dd/MM/yyyy") + "','dd/MM/yyyy')";
        }
        else
        {
            return "";
        }
    }

    public static string String_Num2Text(string mNumber, bool bUpcaseFirst)
    {
        if (mNumber.Contains(CS_DECIMAL_SYMBOL))
        {
            mNumber = mNumber.Substring(0, mNumber.IndexOf(CS_DECIMAL_SYMBOL));
        }
        mNumber = mNumber.Replace(CS_DIGIT_GROUP_SYMBOL, "");
        //
        int mLen = 0;
        int i = 0;
        int mDigit = 0;
        string mTemp = null;
        string[] mNumText = null;
        mNumText = new string[] {
			"không",
			"một",
			"hai",
			"ba",
			"bốn",
			"năm",
			"sáu",
			"bảy",
			"tám",
			"chín"
		};
        mLen = mNumber.Length;
        for (i = 1; i <= mLen; i++)
        {
            mDigit = int.Parse(mNumber[i - 1].ToString());
            mTemp += " " + mNumText[mDigit];
            if ((mLen == i))
                break; // TODO: might not be correct. Was : Exit For
            switch (decimal.Remainder((decimal)(mLen - i), (decimal)9).ToString())
            {
                case "0":
                    mTemp += " tỷ";
                    if (mNumber.Substring(i, 9) == "000000000")
                        i = i + 9;
                    if (i >= mLen)
                        break; // TODO: might not be correct. Was : Exit For

                    if (mNumber.Substring(i, 3) == "000")
                        i = i + 2;
                    //doc ca truong hop "... ty ... khong trieu ... nghin "
                    break;
                //If mNumber.Substring(i, 3) = "000" Then i = i + 3'bo qua truong hop "khong trieu" 
                case "6":
                    mTemp += " triệu";
                    if (mNumber.Substring(i, 6) == "000000")
                        i = i + 6;
                    if (i >= mLen)
                        break; // TODO: might not be correct. Was : Exit For

                    if (mNumber.Substring(i, 3) == "000")
                        i = i + 2;
                    //doc ca truong hop "... trieu ... khong nghin ... "
                    break;
                //If mNumber.Substring(i, 3) = "000" Then i = i + 3'bo qua truong hop "khong nghin" 
                case "3":
                    mTemp += " nghìn";
                    if (mNumber.Substring(i, 3) == "000")
                        i = i + 3;
                    break;
                default:
                    switch (decimal.Remainder((decimal)(mLen - i), (decimal)3).ToString())
                    {
                        case "2":
                            mTemp += " trăm";
                            break;
                        case "1":
                            mTemp += " mươi";
                            break;
                    }
                    break;
            }
        }
        //bo 00
        mTemp = mTemp.Replace("không mươi không", "");
        //truong hop 0x
        mTemp = mTemp.Replace("không mươi ", "linh ");
        mTemp = mTemp.Replace("mươi không", "mươi");
        mTemp = mTemp.Replace("một mươi", "mười");
        //x4 (x>1)
        mTemp = mTemp.Replace("mươi bốn", "mươi tư");
        //04
        mTemp = mTemp.Replace("linh bốn", "linh tư");
        //x5 (x>1)
        //mTemp = mTemp.Replace("mươi năm", "mươi nhăm")
        mTemp = mTemp.Replace("mươi năm", "mươi lăm");
        //x1 (x>1)
        mTemp = mTemp.Replace("mươi một", "mươi mốt");
        //15
        mTemp = mTemp.Replace("mười năm", "mười lăm");
        //clear double space
        mTemp = mTemp.Replace("  ", " ");
        mTemp = mTemp.Trim();
        if (mTemp.StartsWith("linh "))
            mTemp = mTemp.Substring("linh ".Length);
        if (bUpcaseFirst)
            mTemp = mTemp.Substring(0, 1).ToUpper() + mTemp.Substring(1);
        return mTemp;
    }

    public static string String_Num2Text(string mNumber)
    {
        return String_Num2Text(mNumber, true);
    }

    public static string String_Capitalize(string sText)
    {
        string sTemp = "";
        foreach (string sWord in sText.Split(' '))
        {
            if (sWord.Length > 0)
            {
                if (sTemp.Length > 0)
                    sTemp += " ";
                sTemp += sWord.Substring(0, 1).ToUpper();
                if (sWord.Length > 1)
                    sTemp += sWord.Substring(1).ToLower();
            }
        }
        return sTemp;
    }

    public static string String_Abstract(string sText, int iLen, string[] arrBreak = null)
    {
        if (sText == null)
            return "";
        sText = sText.Trim();
        sText = sText.Replace(vbCrLf, " ");
        sText = sText.Replace(vbCr, " ");
        if (sText.Length == 0)
            return "";
        if (sText.Length > iLen)
        {
            sText = sText.Substring(0, iLen);
            int iPos = 0;
            int iTemp = 0;
            if ((arrBreak != null))
            {
                foreach (string sBreak in arrBreak)
                {
                    iTemp = sText.LastIndexOf(sBreak);
                    if (iTemp > iPos)
                        iPos = iTemp;
                }
            }
            if (iPos == 0 || iPos < iLen - 10)
                iPos = sText.LastIndexOf(" ");
            if (iPos > 0)
            {
                sText = sText.Substring(0, iPos);
                //+ " ..."
            }
        }
        return sText;
    }

    public static string String_Compress(string sUncompress)
    {
        string Result = string.Empty;
        //Convert the uncompressed string into a byte array
        byte[] UnZippedData = System.Text.Encoding.UTF8.GetBytes(sUncompress);
        //Compress the byte array
        byte[] ZippedData = ByteArray_Compress(UnZippedData);
        //Convert the compressed byte array back to a string
        Result = System.Convert.ToBase64String(ZippedData);
        //
        return Result;
    }

    public static string String_Decompress(string sCompress)
    {
        string Result = string.Empty;
        byte[] ZippedData = null;
        //Convert the compressed string into a byte array and decrypt the array if required    
        ZippedData = System.Convert.FromBase64String(sCompress);
        //Decompress the byte array
        byte[] UnZippedData = ByteArray_Decompress(ZippedData);
        //Convert the decompressed byte array back to a string
        Result = System.Text.Encoding.UTF8.GetString(UnZippedData);
        //
        return Result;
    }

    public static byte[] ByteArray_Compress(byte[] UnZippedData)
    {
        byte[] Result = null;
        //Compress the byte array
        Result = QuickLZ.compress(UnZippedData, 3);
        return Result;
    }

    public static byte[] ByteArray_Decompress(byte[] ZippedData)
    {
        byte[] Result = null;
        //Decompress the byte array
        Result = QuickLZ.decompress(ZippedData);
        return Result;
    }

    public static Stream Stream_Compress(Stream input)
    {
        if (input == null)
            return null;
        //
        int streamLength = Convert.ToInt32(input.Length);
        byte[] arrBytes = new byte[streamLength];
        // Read the file into a byte array
        input.Read(arrBytes, 0, streamLength);
        input.Close();
        MemoryStream output = new MemoryStream(ByteArray_Compress(arrBytes));
        //
        return output;
    }

    public static Stream Stream_Decompress(Stream input)
    {
        if (input == null)
            return null;
        //
        int streamLength = Convert.ToInt32(input.Length);
        byte[] arrBytes = new byte[streamLength];
        // Read the file into a byte array
        input.Read(arrBytes, 0, streamLength);
        input.Close();
        MemoryStream output = new MemoryStream(ByteArray_Decompress(arrBytes));
        //
        return output;
    }

    public static DataTable Reader2Table(IDataReader objDataReader)
    {
        DataTable dt = new DataTable();
        dt.Load(objDataReader);
        objDataReader.Close();
        objDataReader.Dispose();
        return dt;
    }

    public static DataTable DataPager(DataSet objData, ref int iTotal)
    {
        if (objData.Tables.Count > 1)
        {
            if (objData.Tables[0].Columns.Count == 1 && objData.Tables[0].Rows.Count == 1)
            {
                iTotal = DB_GetValue<Int32>(objData.Tables[0].Rows[0][0], 0);
                return objData.Tables[1];
            }
            else if (objData.Tables[1].Columns.Count == 1 && objData.Tables[1].Rows.Count == 1)
            {
                iTotal = DB_GetValue<Int32>(objData.Tables[1].Rows[0][0], 0);
                return objData.Tables[0];
            }
            else
            {
                return null;
            }
        }
        else
        {
            return null;
        }
    }

    public static void DataTable_SetKey(DataTable dt, string sColName)
    {
        dt.PrimaryKey = new DataColumn[] { dt.Columns[sColName] };
        dt.AcceptChanges();
    }

    public static void DataTable_SetUnique(DataTable dt, params string[] arrColName)
    {
        DataColumn[] arrColumn = (DataColumn[])Array.CreateInstance(typeof(DataColumn), arrColName.Length);
        for (int i = 0; i <= arrColName.Length - 1; i++)
        {
            arrColumn[i] = dt.Columns[arrColName[i]];
        }
        UniqueConstraint uc1 = new UniqueConstraint("uc" + string.Join("_", arrColName), arrColumn);
        dt.Constraints.Add(uc1);
        dt.AcceptChanges();
    }

    public static void DataTable_SetNull(DataTable dt, params string[] arrColName)
    {
        for (int i = 0; i <= arrColName.Length - 1; i++)
        {
            dt.Columns[arrColName[i]].AllowDBNull = true;
        }
        dt.AcceptChanges();
    }

    public static void DataTable_SetNotNull(DataTable dt, params string[] arrColName)
    {
        for (int i = 0; i <= arrColName.Length - 1; i++)
        {
            dt.Columns[arrColName[i]].AllowDBNull = false;
        }
        dt.AcceptChanges();
    }

    //Public Sub DataTable_SetReadOnly(ByVal dt As DataTable, bReadOnly As Boolean, ByVal ParamArray arrColName() As String)
    //    For i As Integer = 0 To arrColName.Length - 1
    //        dt.Columns(arrColName(i)).ReadOnly = bReadOnly
    //    Next
    //    dt.AcceptChanges()
    //End Sub

    public static DataRow DataTable_GetRow(DataTable dt)
    {
        if (dt == null || dt.Rows.Count == 0)
        {
            return null;
        }
        else
        {
            return dt.Rows[0];
        }
    }

    public static void DataTable_UpdateRow(DataTable dt, string rowFilter, string fieldName, object fieldValue)
    {
        string oldFilter = dt.DefaultView.RowFilter;
        dt.DefaultView.RowFilter = rowFilter;
        for (int i = 0; i <= dt.DefaultView.Count - 1; i++)
        {
            dt.DefaultView[i][fieldName] = fieldValue;
        }
        dt.DefaultView.RowFilter = oldFilter;
    }

    public static void DataTable_RowNumber(DataTable dt)
    {
        if (!dt.Columns.Contains("RN"))
        {
            dt.Columns.Add("RN", typeof(Int32));
            for (int i = 0; i <= dt.DefaultView.Count - 1; i++)
            {
                dt.DefaultView[i].Row["RN"] = i + 1;
            }
            dt.AcceptChanges();
        }
    }


    public static void DataTable_SetAutoColumn(DataTable dt, string sColumn)
    {
        if (dt != null)
        {
            DataColumn column;
            if (!dt.Columns.Contains(sColumn))
                column = new DataColumn("STT");
            else
                column = dt.Columns[sColumn];
            //
            column.DataType = System.Type.GetType("System.Int32");
            column.AutoIncrement = true;
            column.AutoIncrementSeed = 0;
            column.AutoIncrementStep = 1;
            //
            if (!dt.Columns.Contains(sColumn))
                dt.Columns.Add(column);
            //

            for (int i = 0; i < dt.Rows.Count; i++)
            {
                dt.Rows[i][sColumn] = i + 1;
            }
            dt.AcceptChanges();
        }
    }

    public static DataRow DataView_FindRow(DataTable dt, string columnName, object columnValue)
    {
        return DataView_FindRow(dt, columnName, columnValue, -1);
    }

    public static DataRow DataView_FindRow(DataTable dt, string columnName, object columnValue, int execeptIndex)
    {
        return DataView_FindRow(dt.DefaultView, columnName, columnValue, execeptIndex);
    }

    public static DataRow DataView_FindRow(DataView dtView, string columnName, object columnValue)
    {
        return DataView_FindRow(dtView, columnName, columnValue, -1);
    }

    public static DataRow DataView_FindRow(DataView dtView, string columnName, object columnValue, int execeptIndex)
    {
        for (int i = 0; i <= dtView.Count - 1; i++)
        {
            if (i != execeptIndex && dtView[i][columnName] == columnValue)
            {
                return dtView[i].Row;
            }
        }
        return null;
    }

    public static DataRow DataView_FindRow(DataTable dt, string filter)
    {
        return DataView_FindRow(dt.DefaultView, filter);
    }

    public static DataRow DataView_FindRow(DataView dtView, string filter)
    {
        DataRow retVal = null;
        string oldFilter = dtView.RowFilter;
        dtView.RowFilter = filter;
        if (dtView.Count > 0)
        {
            retVal = dtView[0].Row;
        }
        dtView.RowFilter = oldFilter;
        return retVal;
    }

    public static void DataRow_FillObject(DataRow dtRow, Standard_Info objInfo)
    {
        DataRow_FillObject(dtRow, objInfo, null);
    }

    public static void DataRow_FillObject(DataRow dtRow, Standard_Info objInfo, FormatInvoker customFormat)
    {
        if (objInfo == null)
            throw new ArgumentNullException("objInfo");
        //
        string sPropertyName = null;
        Type objType = objInfo.GetType();
        PropertyInfo objProperty = default(PropertyInfo);
        foreach (DataColumn dtCol in dtRow.Table.Columns)
        {
            sPropertyName = dtCol.ColumnName;
            objProperty = Object_GetProperty(objType, sPropertyName);
            if ((objProperty != null) && objProperty.CanWrite)
            {
                object objValue = dtRow[sPropertyName];
                if (customFormat != null)
                    customFormat.Invoke(sPropertyName, ref objValue);
                if (objValue == DBNull.Value)
                {
                    objProperty.SetValue(objInfo, Null.SetNull(objProperty), null);
                }
                else
                {
                    if (objProperty.PropertyType.Equals(typeof(bool)))
                    {
                        objProperty.SetValue(objInfo, Globals.Object_SetValueEx<bool>(objValue), null);
                    }
                    else
                    {
                        objProperty.SetValue(objInfo, Convert.ChangeType(objValue, objProperty.PropertyType), null);
                    }

                }
            }
        }
    }

    public static void DataRow_FillData(DataRow dtRow, Standard_Info objInfo)
    {
        DataRow_FillData(dtRow, objInfo, null);
    }

    public static void DataRow_FillData(DataRow dtRow, Standard_Info objInfo, FormatInvoker customFormat)
    {
        if (objInfo == null)
            throw new ArgumentNullException("objInfo");
        //
        string sPropertyName = null;
        Type objType = objInfo.GetType();
        PropertyInfo objProperty = default(PropertyInfo);
        foreach (DataColumn dtCol in dtRow.Table.Columns)
        {
            sPropertyName = dtCol.ColumnName;
            objProperty = Object_GetProperty(objType, sPropertyName);
            if ((objProperty != null) && objProperty.CanRead)
            {
                object objValue = objProperty.GetValue(objInfo, null);
                if (customFormat != null)
                    customFormat.Invoke(sPropertyName, ref objValue);
                if (dtCol.AllowDBNull)
                {
                    dtRow[sPropertyName] = DB_GetNull(objValue);
                }
                else
                {
                    dtRow[sPropertyName] = objValue;
                }
            }
        }
    }

    public static void DataRow_Copy(DataRow dtRowSrc, DataRow dtRowDest)
    {
        foreach (DataColumn dtCol in dtRowSrc.Table.Columns)
        {
            if (dtRowDest.Table.Columns.Contains(dtCol.ColumnName))
            {
                dtRowDest[dtCol.ColumnName] = dtRowSrc[dtCol.ColumnName];
            }
        }
    }

    public static void DataRow_Copy(DataRow dtRowSrc, System.Windows.Forms.DataGridViewRow dtRowDest)
    {
        foreach (DataColumn dtCol in dtRowSrc.Table.Columns)
        {
            if (dtRowDest.DataGridView.Columns.Contains(dtCol.ColumnName))
            {
                dtRowDest.Cells[dtCol.ColumnName].Value = dtRowSrc[dtCol.ColumnName];
            }
        }
    }

    public static object Reader_GetValue(IDataReader rd, string sItemName)
    {
        int iIndex = 0;
        iIndex = Reader_ColumnIndex(rd, sItemName);
        if (iIndex >= 0)
        {
            return rd[iIndex];
        }
        else
        {
            return null;
        }
    }

    public static object Reader_GetValue(IDataReader rd, string sItemName, Dictionary<string, int> dicColumn)
    {
        int iIndex = 0;
        if (dicColumn.ContainsKey(sItemName))
        {
            iIndex = dicColumn[sItemName];
        }
        else
        {
            iIndex = Reader_ColumnIndex(rd, sItemName);
            dicColumn.Add(sItemName, iIndex);
        }
        if (iIndex >= 0)
        {
            return rd[iIndex];
        }
        else
        {
            return null;
        }
    }

    public static Dictionary<string, int> Reader_ColumnList(IDataReader rd)
    {
        Dictionary<string, int> rt = new Dictionary<string, int>();
        for (int i = 0; i <= rd.FieldCount - 1; i++)
        {
            rt.Add(rd.GetName(i), i);
        }
        return rt;
    }

    public static int Reader_ColumnIndex(IDataReader rd, string sColumn)
    {
        //For i As Integer = 0 To rd.FieldCount - 1
        //    If sColumn.Equals(rd.GetName(i), StringComparison.CurrentCultureIgnoreCase) Then
        //        Return i
        //    End If
        //Next
        //Return -1
        try
        {
            return rd.GetOrdinal(sColumn);
        }
        catch
        {
            return -1;
        }
    }

    //public static byte[] DataTable_Serialize(DataTable dt)
    //{
    //    return AdoNetHelper.SerializeDataTable(dt);
    //}

    //public static DataTable DataTable_Deserialize(byte[] bin)
    //{
    //    return AdoNetHelper.DeserializeDataTable(bin);
    //}

    public static byte[] DataTable_BinarySerialize(DataTable dt)
    {
        System.IO.MemoryStream stream = new System.IO.MemoryStream();
        System.Runtime.Serialization.IFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
        formatter.Serialize(stream, dt);
        return stream.ToArray();
    }


    public static DataTable DataTable_BinaryDeserialize(byte[] buffer)
    {
        System.IO.MemoryStream stream = new System.IO.MemoryStream(buffer);
        System.Runtime.Serialization.IFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();

        return formatter.Deserialize(stream) as DataTable;
    }

    public static byte[] DataTable_Serialize(DataTable dtTable)
    {
        if (dtTable == default(System.Data.DataTable))
            return default(byte[]);

        System.IO.MemoryStream memStream = new System.IO.MemoryStream();
        System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(System.Data.DataTable));
        serializer.Serialize(memStream, dtTable);

        return memStream.ToArray();
    }


    public static System.Data.DataTable DataTable_Deserialize(byte[] tableBytes)
    {
        System.IO.MemoryStream memStream = new System.IO.MemoryStream(tableBytes);
        System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(System.Data.DataTable));
        System.Data.DataTable dt = (System.Data.DataTable)serializer.Deserialize(memStream);
        return dt;
    }

    public static byte[] DataSet_Serialize(System.Data.DataSet ds)
    {
        if (ds == default(System.Data.DataSet))
            return default(byte[]);

        System.IO.MemoryStream memStream = new System.IO.MemoryStream();
        System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(System.Data.DataTable));
        serializer.Serialize(memStream, ds);

        return memStream.ToArray();
    }


    public static System.Data.DataSet DataSet_Deserialize(byte[] tableBytes)
    {
        System.IO.MemoryStream memStream = new System.IO.MemoryStream(tableBytes);
        System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(System.Data.DataSet));
        System.Data.DataSet ds = (System.Data.DataSet)serializer.Deserialize(memStream);
        return ds;
    }

    public static void Reader_Close(IDataReader obj)
    {
        if (obj == null)
            return;
        obj.Close();
        obj.Dispose();
    }

    public static void Object_SetValue(object objSource, ref object objDest)
    {
        //Purpose: 
        //   Sử dụng để gán giá trị từ kiểu dữ liệu này sang kiểu dữ liệu khác
        //Parameters: 
        //   objSource : dữ liệu nguồn
        //   objDest   : dữ liệu đích
        //Notes:
        //   
        object sValue = null;
        if ((objSource != null))
        {
            //
            if (objSource.GetType().Namespace == "System.Windows.Forms")
                throw new Exception("Param objSource don't support type " + objSource.GetType().Name);
            //
            if (objDest.GetType().Name == objSource.GetType().Name)
            {
                objDest = objSource;
                return;
            }
            else if (object.ReferenceEquals(objSource, DBNull.Value))
            {
                objDest = Null.SetNull(DBNull.Value, objDest);
                return;
            }
            else
            {
                sValue = objSource.ToString();
            }
        }
        else
        {
            sValue = "";
        }
        if (objDest == null)
        {
            objDest = sValue;
        }
        else
        {
            objDest = Object_SetValueEx(sValue, objDest.GetType().Name);
        }
    }

    public static bool Type_IsNumeric(Type type)
    {
        if (type == null)
        {
            return false;
        }

        switch (Type.GetTypeCode(type))
        {
            case TypeCode.Byte:
            case TypeCode.Decimal:
            case TypeCode.Double:
            case TypeCode.Int16:
            case TypeCode.Int32:
            case TypeCode.Int64:
            case TypeCode.SByte:
            case TypeCode.Single:
            case TypeCode.UInt16:
            case TypeCode.UInt32:
            case TypeCode.UInt64:
                return true;
            case TypeCode.Object:
                if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
                {
                    return Type_IsNumeric(Nullable.GetUnderlyingType(type));
                }
                return false;
        }
        return false;
    }

    public static string Object_GetString(object objValue, string stringFormat)
    {
        try
        {
            if (objValue is Int32)
                return ((Int32)objValue).ToString(!String.IsNullOrEmpty(stringFormat) ? stringFormat : CS_DISPLAY_NUMBER_FORMAT);
            else if (objValue is Int16)
                return ((Int16)objValue).ToString(!String.IsNullOrEmpty(stringFormat) ? stringFormat : CS_DISPLAY_NUMBER_FORMAT);
            else if (objValue is Int64)
                return ((Int64)objValue).ToString(!String.IsNullOrEmpty(stringFormat) ? stringFormat : CS_DISPLAY_NUMBER_FORMAT);
            else if (objValue is decimal)
                return ((Decimal)objValue).ToString(!String.IsNullOrEmpty(stringFormat) ? stringFormat : CS_DISPLAY_NUMBER_FORMAT);
            else if (objValue is double)
                return ((Decimal)objValue).ToString(!String.IsNullOrEmpty(stringFormat) ? stringFormat : CS_DISPLAY_NUMBER_FORMAT);
            else if (objValue is float)
                return ((float)objValue).ToString(!String.IsNullOrEmpty(stringFormat) ? stringFormat : CS_DISPLAY_NUMBER_FORMAT);
            else if (objValue is DateTime)
                return ((DateTime)objValue).ToString(!String.IsNullOrEmpty(stringFormat) ? stringFormat : CS_DISPLAY_DATE_FORMAT);
            else if (objValue is string)
                return (string)objValue;
            else
                return objValue.ToString();
        }
        catch (Exception)
        {

            return Null.GetNull(objValue, Null.NullString).ToString();
        }
    }

    public static T Object_GetValue<T>(object sValue)
    {
        T objReturn = default(T);
        if (sValue == null)
        {
            return (T)Null.SetNullValue(objReturn);
        }
        else
        {
            if ((objReturn == null))
            {
                return (T)Object_SetValueEx(sValue, "String", false);
            }
            else
            {
                return (T)Object_SetValueEx(sValue, objReturn.GetType().Name, false);
            }
        }
    }

    public static T Object_SetValueEx<T>(object sValue)
    {
        T objReturn = default(T);
        if (sValue == null)
        {
            return (T)Null.SetNullValue(objReturn);
        }
        else
        {
            if ((objReturn == null))
            {
                return (T)Object_SetValueEx(sValue, "String", false);
            }
            else
            {
                return (T)Object_SetValueEx(sValue, objReturn.GetType().Name, false);
            }
        }
    }

    static internal readonly string[] cs_Type_DateTime = {
		"DATETIME",
		"DATE"
	};
    static internal readonly string[] cs_Type_Short = {
		"SHORT",
		"INT16",
		"SMALLINT"
	};
    static internal readonly string[] cs_Type_Integer = {
		"INTEGER",
		"INT32",
		"INT"
	};
    static internal readonly string[] cs_Type_Long = {
		"LONG",
		"INT64",
		"BIGINT"
	};
    static internal readonly string[] cs_Type_Byte = {
		"BYTE",
		"TINYINT"
	};
    static internal readonly string[] cs_Type_Double = {
		"DOUBLE",
		"FLOAT"
	};
    static internal readonly string[] cs_Type_Single = { "SINGLE" };
    static internal readonly string[] cs_Type_Decimal = {
		"DECIMAL",
		"NUMERIC",
		"MONEY",
		"NUMBER"
	};
    static internal readonly string[] cs_Type_Boolean = {
		"BOOLEAN",
		"BIT"
	};
    static internal readonly string[] cs_Type_String = {
		"STRING",
		"TEXT",
		"NTEXT"

	};
    public static object Object_SetValueEx(object inputValue, string outputType, bool bForDB = false)
    {
        object outputValue = null;
        string inputType = null;
        if ((inputValue != null))
            inputType = inputValue.GetType().Name.ToUpper();
        outputType = outputType.ToUpper();
        if (inputType == outputType)
        {
            return inputValue;
        }
        else
        {
            if (cs_Type_DateTime.Contains(outputType))
            {
                if (cs_Type_DateTime.Contains(inputType))
                    return inputValue;
                DateTime dtTmp = DateTime.MinValue;
                if (!Date_TryParseEx(inputValue.ToString(), ref dtTmp))
                {
                    if (bForDB)
                    {
                        outputValue = DBNull.Value;
                    }
                    else
                    {
                        outputValue = Null.NullDate;
                    }
                }
                else
                    outputValue = dtTmp;
            }
            else if (cs_Type_Long.Contains(outputType))
            {
                if (cs_Type_Long.Contains(inputType))
                    return inputValue;
                if ((inputValue != null))
                    inputValue = inputValue.ToString().Replace(CS_DIGIT_GROUP_SYMBOL, "");
                if (IsNumeric(inputValue))
                {
                    outputValue = decimal.ToInt64(decimal.Parse(inputValue.ToString()));
                }
                else
                {
                    if (bForDB)
                    {
                        outputValue = DBNull.Value;
                    }
                    else
                    {
                        outputValue = Null.NullLong;
                    }
                }
            }
            else if (cs_Type_Integer.Contains(outputType))
            {
                if (cs_Type_Integer.Contains(inputType))
                    return inputValue;
                if ((inputValue != null))
                    inputValue = inputValue.ToString().Replace(CS_DIGIT_GROUP_SYMBOL, "");
                if (IsNumeric(inputValue))
                {
                    outputValue = decimal.ToInt32(decimal.Parse(inputValue.ToString()));
                }
                else
                {
                    if (bForDB)
                    {
                        outputValue = DBNull.Value;
                    }
                    else
                    {
                        outputValue = Null.NullInteger;
                    }
                }
            }
            else if (cs_Type_Short.Contains(outputType))
            {
                if (cs_Type_Short.Contains(inputType))
                    return inputValue;
                if ((inputValue != null))
                    inputValue = inputValue.ToString().Replace(CS_DIGIT_GROUP_SYMBOL, "");
                if (IsNumeric(inputValue))
                {
                    outputValue = decimal.ToInt16(decimal.Parse(inputValue.ToString()));
                }
                else
                {
                    if (bForDB)
                    {
                        outputValue = DBNull.Value;
                    }
                    else
                    {
                        outputValue = Null.NullShort;
                    }
                }
            }
            else if (cs_Type_Byte.Contains(outputType))
            {
                if (cs_Type_Byte.Contains(inputType))
                    return inputValue;
                if ((inputValue != null))
                    inputValue = inputValue.ToString().Replace(CS_DIGIT_GROUP_SYMBOL, "");
                if (IsNumeric(inputValue))
                {
                    outputValue = decimal.ToByte(decimal.Parse(inputValue.ToString()));
                }
                else
                {
                    if (bForDB)
                    {
                        outputValue = DBNull.Value;
                    }
                    else
                    {
                        outputValue = byte.MinValue;
                    }
                }
            }
            else if (cs_Type_Double.Contains(outputType))
            {
                if (cs_Type_Double.Contains(inputType))
                    return inputValue;
                if ((inputValue != null))
                    inputValue = inputValue.ToString().Replace(CS_DIGIT_GROUP_SYMBOL, "");
                if (IsNumeric(inputValue))
                {
                    outputValue = double.Parse(inputValue.ToString());
                }
                else
                {
                    if (bForDB)
                    {
                        outputValue = DBNull.Value;
                    }
                    else
                    {
                        outputValue = Null.NullDouble;
                    }
                }
            }
            else if (cs_Type_Single.Contains(outputType))
            {
                if (cs_Type_Single.Contains(inputType))
                    return inputValue;
                if ((inputValue != null))
                    inputValue = inputValue.ToString().Replace(CS_DIGIT_GROUP_SYMBOL, "");
                if (IsNumeric(inputValue))
                {
                    outputValue = float.Parse(inputValue.ToString());
                }
                else
                {
                    if (bForDB)
                    {
                        outputValue = DBNull.Value;
                    }
                    else
                    {
                        outputValue = Null.NullSingle;
                    }
                }
            }
            else if (cs_Type_Decimal.Contains(outputType))
            {
                if (cs_Type_Decimal.Contains(inputType))
                    return inputValue;
                if ((inputValue != null))
                    inputValue = inputValue.ToString().Replace(CS_DIGIT_GROUP_SYMBOL, "");
                if (IsNumeric(inputValue) || IsDecimal(inputValue))
                {
                    outputValue = decimal.Parse(inputValue.ToString());
                }
                else
                {
                    if (bForDB)
                    {
                        outputValue = DBNull.Value;
                    }
                    else
                    {
                        outputValue = Null.NullDecimal;
                    }
                }
            }
            else if (cs_Type_String.Contains(outputType))
            {
                if (cs_Type_String.Contains(inputType))
                    return inputValue;
                if (object.ReferenceEquals(inputValue, DBNull.Value) || inputValue == null)
                {
                    outputValue = "";
                }
                else
                {
                    //Convert array to string
                    if (inputType.EndsWith("[]"))
                    {
                        outputValue = ArrayToString(new object[] { inputValue });
                    }
                    else
                    {
                        outputValue = inputValue.ToString();
                    }
                }
                if (bForDB && string.IsNullOrEmpty((string)outputValue))
                {
                    outputValue = DBNull.Value;
                }
            }
            else if (cs_Type_Boolean.Contains(outputType))
            {
                if (cs_Type_Boolean.Contains(inputType))
                    return inputValue;
                if (object.ReferenceEquals(inputValue, DBNull.Value) || inputValue == null)
                {
                    outputValue = false;
                }
                else
                {
                    bool bOutputValue = false;
                    if (!bool.TryParse(inputValue.ToString(), out bOutputValue))
                    {
                        switch (inputValue.ToString().ToUpper())
                        {
                            case "YES":
                            case "Y":
                            case "TRUE":
                            case "T":
                            case "1":
                                outputValue = true;
                                break;
                            default:
                                outputValue = false;
                                break;
                        }
                    }
                }
            }
            else if ("GUID".Contains(outputType))
            {
                if (string.IsNullOrEmpty(inputValue.ToString()))
                {
                    outputValue = Null.NullGuid;
                }
                else
                {
                    try
                    {
                        outputValue = new Guid(inputValue.ToString());
                    }
                    catch
                    {
                        outputValue = Null.NullGuid;
                    }
                }
                if (bForDB && (Guid)outputValue == Null.NullGuid)
                {
                    outputValue = DBNull.Value;
                }
            }
            else
            {
                if (object.ReferenceEquals(inputValue, DBNull.Value))
                {
                    outputValue = null;
                }
                else
                {
                    outputValue = inputValue;
                }
            }
        }
        return outputValue;
    }

    public static string Object_GetDisplayValue(object objSource)
    {
        return Object_GetDisplayValue(objSource, "");
    }

    public static string Object_GetDisplayValue(object objSource, string sNullValue)
    {
        return Object_GetDisplayValue(objSource, sNullValue, true);
    }

    public static string Object_GetDisplayValue(object objSource, string sNullValue, bool bFormat)
    {
        //Purpose: 
        //   Customize ToString 
        //Parameters: 
        //   objSource : dữ liệu nguồn
        //Notes:
        //   Đối với dữ liệu kiểu Date sẽ tự chuyển thành CS_DISPLAY_DATE_FORMAT
        //   Đối với dữ liệu kiểu Numeric sẽ tự format 0,000.00 và tự động bỏ các số 0 thừa

        if (objSource is bool)
        {
            if (Convert.ToBoolean(objSource) == true)
            {
                return "Yes";
            }
            else
            {
                return "No";
            }
        }
        else
        {
            if (Null.IsNull(objSource))
            {
                return sNullValue;
            }
            else
            {
                if (objSource is System.DateTime)
                {
                    if (bFormat)
                    {
                        return Convert.ToDateTime(objSource).ToString(CS_DISPLAY_DATE_FORMAT);
                    }
                    else
                    {
                        return Convert.ToDateTime(objSource).ToShortDateString();
                    }
                }
                else
                {
                    if (bFormat && (!(objSource is string)) && IsNumeric(objSource))
                    {
                        objSource = (object)FormatNumberEx(Convert.ToDecimal(objSource), 4);
                    }
                    return objSource.ToString();
                }
            }
        }
    }

    public static bool IsNumeric(object inputString)
    {
        return Regex.IsMatch(inputString.ToString(), "^[0-9]+$");
        //return Regex.IsMatch(inputString.ToString(), "^[0-9]+[" + Globals.CS_DECIMAL_SYMBOL + "0]+$");
    }

    public static bool IsDecimal(object inputString)
    {
        return Regex.IsMatch(inputString.ToString(), @"^[-+]?(\d{1,3}((,\d{3})*(\.\d+)?|([.\s]\d{3})*(,\d+)?)|\d+([,\.]\d+)?)$");
        //return Regex.IsMatch(inputString.ToString(), "^[0-9]+[" + Globals.CS_DECIMAL_SYMBOL + "0]+$");
    }


    public static string Enum_GetName(Enum eValue)
    {
        return Enum.GetName(eValue.GetType(), eValue);
    }

    public static string FormatNumberEx(decimal objSource, Int16 iDecimal)
    {
        string sFormat = "#,##0";
        if (iDecimal > 0)
        {
            sFormat += "." + new string('0', iDecimal);
        }
        else if (iDecimal <= 0)
        {
            objSource = objSource / (decimal)Math.Pow(10, -(double)iDecimal);
            //Else
            sFormat = "#,##0";
        }
        string sReturn = objSource.ToString(sFormat);
        //FormatNumber(objSource, , TriState.False)
        string sDecChar = null;
        sDecChar = System.Threading.Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator;
        //
        int iPos = sReturn.ToString().LastIndexOf(sDecChar);
        if (iPos > -1)
        {
            string sDecNum = sReturn.ToString().Substring(iPos);
            while (!(string.IsNullOrEmpty(sDecNum)))
            {
                if (sDecNum.Substring(sDecNum.Length - 1) != "0")
                {
                    break; // TODO: might not be correct. Was : Exit Do
                }
                else
                {
                    sDecNum = sDecNum.Substring(0, sDecNum.Length - 1);
                }
            }
            if (sDecNum == sDecChar)
                sDecNum = "";
            sReturn = sReturn.Substring(0, iPos) + sDecNum;
            if (sReturn.Length == 0)
                sReturn = "0";
        }
        return sReturn;
    }

    public static string Time_GetValue(System.DateTime objSource, bool bSuppressNull = true)
    {
        string sReturn = objSource.ToString("HH:mm");
        if (bSuppressNull && sReturn == "00:00")
        {
            sReturn = "";
        }
        return sReturn;
    }

    public static void DateTime_SetValue(string objSource, ref System.DateTime objDest)
    {
        objDest = Date_ParseEx(objSource);
    }

    public static object Object_GetPropertyValue(object objObject, string sPropertyName)
    {
        if (objObject == null)
            throw new ArgumentNullException("objObject");
        PropertyInfo objProp = Object_GetProperty(objObject.GetType(), sPropertyName);
        object objReturn = null;
        if ((objProp != null) && objProp.CanRead)
        {
            objReturn = objProp.GetValue(objObject, null);
        }
        return objReturn;
    }

    public static object Object_GetPropertyValue(object objObject, int iPropertyIndex)
    {
        if (objObject == null)
            throw new ArgumentNullException("objObject");
        Type objType = objObject.GetType();
        PropertyInfo objProperty = (PropertyInfo)CBO.GetPropertyInfo(objType)[iPropertyIndex];
        //objType.GetProperties.GetValue(iPropertyIndex)
        if (objProperty == null)
        {
            return null;
        }
        else
        {
            return objProperty.GetValue(objObject, null);
        }
    }

    public static PropertyInfo Object_GetProperty(Type objType, string sPropertyName)
    {
        PropertyInfo objReturn = objType.GetProperty(sPropertyName);
        //Ignore Case
        if (objReturn == null)
        {

            ArrayList arr = CBO.GetPropertyInfo(objType);

            //List<PropertyInfo> arr = CBO.GetPropertyInfo(objType);

            foreach (PropertyInfo obj in arr)
            {
                if (obj.Name.ToUpper() == sPropertyName.ToUpper())
                {
                    objReturn = obj;
                    break; // TODO: might not be correct. Was : Exit For
                }
            }
        }
        return objReturn;
    }

    public static int Object_GetPropertyIndex(Type objType, ref string sPropertyName)
    {
        //List<PropertyInfo> arr = CBO.GetPropertyInfo(objType);
        ArrayList arr = CBO.GetPropertyInfo(objType);
        PropertyInfo objReturn = objType.GetProperty(sPropertyName);
        //Ignore Case
        if (objReturn == null)
        {
            return Object_GetPropertyIndex(arr, ref sPropertyName);
        }
        else
        {
            return arr.IndexOf(objReturn);
        }
    }

    public static int Object_GetPropertyIndex(ArrayList arrProperty, ref string sPropertyName)
    {
        PropertyInfo objReturn = default(PropertyInfo);
        for (int i = 0; i <= arrProperty.Count - 1; i++)
        {
            objReturn = (PropertyInfo)arrProperty[i];
            if (objReturn.Name.ToUpper() == sPropertyName.ToUpper())
            {
                sPropertyName = objReturn.Name;
                return i;
            }
        }
        return -1;
    }

    public static bool Object_Compare(object Object1, object Object2)
    {
        //Purpose: 
        //   Hỗ trợ cho phần SetComboValue
        //   So sánh 2 Object dựa trên Properties
        //Parameters: 
        //
        //Notes
        //   Chú ý nếu trong phần định nghĩa prototye của Object 
        //   có trường PK lưu tên của thuộc tính PK
        //   thì khi compare chỉ compare các thuộc tính PK này
        bool mReturn = true;
        PropertyInfo objProperty = default(PropertyInfo);

        objProperty = Object1.GetType().GetProperty("PK");


        if ((objProperty != null))
        {
            string[] arrPK = Convert.ToString(objProperty.GetValue(Object1, null)).Split(new char[] { ';' });
            for (long i = 0; i <= arrPK.GetUpperBound(0); i++)
            {
                objProperty = Object1.GetType().GetProperty(arrPK[i]);
                if (objProperty == null)
                {
                    mReturn = false;
                    break; // TODO: might not be correct. Was : Exit For
                }
                else
                {
                    if (objProperty.GetValue(Object1, null) != objProperty.GetValue(Object2, null))
                    {
                        mReturn = false;
                        break; // TODO: might not be correct. Was : Exit For
                    }
                }
            }
        }
        if (!mReturn)
        {
            foreach (PropertyInfo objPropertyTmp in Object1.GetType().GetProperties())
            {
                if (objPropertyTmp.GetValue(Object1, null) != objPropertyTmp.GetValue(Object2, null))
                {
                    mReturn = false;
                    break; // TODO: might not be correct. Was : Exit For
                }
            }
        }
        return mReturn;
    }

    //Private cache mapping table column index with object property

    private static Dictionary<string, List<int>> m_cacheTableColumn = new Dictionary<string, List<int>>();
    public static T DataRow_FillObject<T>(DataRow dtRow)
    {
        T objObject = Activator.CreateInstance<T>();
        DataRow_FillObject(dtRow, objObject);
        return objObject;
    }

    public static void DataRow_FillObject(DataRow dtRow, object objObject)
    {
        //
        Type objType = objObject.GetType();
        PropertyInfo objProperty = default(PropertyInfo);
        PropertyInfo[] arrProperty = objType.GetProperties();
        string sKey = objType.Name + "_" + dtRow.Table.Columns.Count.ToString();
        List<int> dicIndex = default(List<int>);
        //----------------
        if ((m_cacheTableColumn != null) && m_cacheTableColumn.ContainsKey(sKey))
        {
            dicIndex = m_cacheTableColumn[sKey];
            for (int iPro = 0; iPro <= dicIndex.Count - 1; iPro++)
            {
                int iField = dicIndex[iPro];
                if (iField == -1)
                    continue;
                Object_SetPropertyValue(ref objObject, arrProperty[iPro], dtRow[iField]);
            }
        }
        else
        {
            dicIndex = new List<int>();
            for (int iProIndex = 0; iProIndex <= arrProperty.Length - 1; iProIndex++)
            {
                objProperty = arrProperty[iProIndex];
                int iIndex = 0;
                if (objProperty.CanWrite)
                {
                    iIndex = dtRow.Table.Columns.IndexOf(objProperty.Name);
                    if (iIndex > -1)
                    {
                        Object_SetPropertyValue(ref objObject, objProperty, dtRow[iIndex]);
                    }
                }
                else
                {
                    iIndex = -1;
                }
                dicIndex.Add(iIndex);
            }
            if (m_cacheTableColumn == null)
                m_cacheTableColumn = new Dictionary<string, List<int>>();
            m_cacheTableColumn.Add(sKey, dicIndex);
        }
    }

    public static void Object_SetPropertyValue(ref object objObject, PropertyInfo objPropertyInfo, object objValue)
    {
        if (objValue == DBNull.Value)
        {
            // translate Null value
            objPropertyInfo.SetValue(objObject, Null.SetNull(objPropertyInfo), null);
        }
        else
        {
            try
            {
                // try implicit conversion first
                objPropertyInfo.SetValue(objObject, objValue, null);
            }
            catch
            {
                Type objPropertyType = default(Type);
                // business object info class member data type does not match datareader member data type
                objPropertyType = objPropertyInfo.PropertyType;
                try
                {
                    //need to handle enumeration conversions differently than other base types
                    if (objPropertyType.IsEnum)
                    {
                        // check if value is numeric and if not convert to integer ( supports databases like Oracle )
                        if (IsNumeric(objValue))
                        {
                            objPropertyInfo.SetValue(objObject, System.Enum.ToObject(objPropertyType, Convert.ToInt32(objValue)), null);
                        }
                        else
                        {
                            objPropertyInfo.SetValue(objObject, System.Enum.ToObject(objPropertyType, objValue), null);
                        }
                    }
                    else
                    {
                        // try explicit conversion
                        objPropertyInfo.SetValue(objObject, Convert.ChangeType(objValue, objPropertyType), null);
                    }
                }
                catch
                {
                    if (objPropertyType.Name == "Boolean")
                    {
                        objPropertyInfo.SetValue(objObject, Convert.ToBoolean(objValue), null);
                    }
                    else
                    {
                        objPropertyInfo.SetValue(objObject, Convert.ChangeType(objValue, objPropertyType), null);
                    }
                }
            }
        }
    }

    public static object DataRow_FillObject(DataRow dtRow, Type objType)
    {
        object objObject = Activator.CreateInstance(objType);
        DataRow_FillObject(dtRow, objObject);
        return objObject;
    }

    public static List<object> DataTable_FillList(DataTable dtTable, Type objType)
    {
        if (dtTable.Rows.Count == 0)
            return null;
        List<object> retVal = new List<object>();
        foreach (DataRow dr in dtTable.Rows)
        {
            object objObject = Activator.CreateInstance(objType);
            DataRow_FillObject(dr, objObject);
            retVal.Add(objObject);
        }
        return retVal;
    }

    public static List<T> DataTable_FillList<T>(DataTable dtTable)
    {
        if (dtTable.Rows.Count == 0)
            return null;
        List<T> retVal = new List<T>();
        foreach (DataRow dr in dtTable.Rows)
        {
            T objObject = Activator.CreateInstance<T>();
            DataRow_FillObject(dr, objObject);
            retVal.Add(objObject);
        }
        return retVal;
    }

    public static bool Date_TryParseEx(string sValue, string sFormat, ref System.DateTime dReturn)
    {
        if (System.DateTime.TryParseExact(sValue, sFormat, System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.AdjustToUniversal, out dReturn))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    public static bool Date_TryParseEx(string sValue, ref System.DateTime dReturn)
    {
        if (System.DateTime.TryParseExact(sValue, CS_EDIT_DATETIME_FORMAT, System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.AdjustToUniversal, out dReturn))
        {
            return true;
        }
        else if (System.DateTime.TryParseExact(sValue, CS_DISPLAY_DATETIME_FORMAT, System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.AdjustToUniversal, out dReturn))
        {
            return true;
        }
        else if (System.DateTime.TryParseExact(sValue, CS_EDIT_DATE_FORMAT, System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.AdjustToUniversal, out dReturn))
        {
            return true;
        }
        else if (System.DateTime.TryParseExact(sValue, CS_DISPLAY_DATE_FORMAT, System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.AdjustToUniversal, out dReturn))
        {
            return true;
        }
        else
        {
            if (System.DateTime.TryParse(sValue, out dReturn))
            {
                return true;
            }
        }
        return false;
    }

    public static void Date_FixString(ref string sValue, bool bShortDate = false)
    {
        DateTime dtTmp;
        if (!System.DateTime.TryParse(sValue, out dtTmp) || sValue.Length > 4)
        {
            sValue = sValue.Replace(" ", "/");
            sValue = sValue.Replace("-", "/");
            if (sValue.Length == 8 && Regex.IsMatch(sValue, "\\b\\d{8}\\b"))
            {
                sValue = sValue.Substring(0, 2) + "/" + sValue.Substring(2, 2) + "/" + sValue.Substring(4, 4);
            }
            else if (sValue.Length == 6 && Regex.IsMatch(sValue, "\\b\\d{6}\\b"))
            {
                System.DateTime dt = System.DateTime.Parse("01/01/" + sValue.Substring(4, 2));
                sValue = sValue.Substring(0, 2) + "/" + sValue.Substring(2, 2) + "/" + dt.Year;

                if (bShortDate)
                    sValue = sValue.Substring(0, 2) + "/" + dt.Year.ToString();
            }
            else if (sValue.Length == 4 && Regex.IsMatch(sValue, "\\b\\d{4}\\b"))
            {
                string sTmp = sValue.Substring(0, 2) + "/" + sValue.Substring(2, 2);
                
                
                
                if (!bShortDate)
                    sValue = sTmp + "/" + DateTime.Today.Year;
                else
                    sValue = sValue.Substring(0, 2) + "/" + "20" + sValue.Substring(2, 2);
            }
            else if (sValue.Length == 5 && Regex.IsMatch(sValue, "\\b\\d{2}\\/\\d{2}\\b"))
            {
                if (!bShortDate)
                    sValue = sValue + "/" + DateTime.Today.Year;
            }
            else if (sValue.Length == 2 && Regex.IsMatch(sValue, "\\b\\d{2}\\b"))
            {
                if (int.Parse(sValue) < 32)
                {
                    sValue += "/" + DateTime.Today.Month.ToString().PadLeft(2, '0');
                    if (!bShortDate)
                        sValue = sValue + "/" + DateTime.Today.Year;
                }
            }
        }
    }

    public static void Time_FixString(ref string sValue)
    {
        DateTime dtTmp;
        if (!System.DateTime.TryParse(sValue, out dtTmp) || sValue.Length > 0)
        {
            if (sValue.Length == 4 && Regex.IsMatch(sValue, "\\b\\d{4}\\b"))
            {
                sValue = sValue.Substring(0, 2) + ":" + sValue.Substring(2, 2);
            }
            else if (sValue.Length == 3 && Regex.IsMatch(sValue, "\\b\\d{3}\\b"))
            {
                sValue = sValue.Substring(0, 1) + ":" + sValue.Substring(1, 2);
            }
            else if (sValue.Length == 2 && Regex.IsMatch(sValue, "\\b\\d{2}\\b"))
            {
                sValue = sValue + ":00";
            }
        }
    }

    public static System.DateTime Time_ParseEx(string dateValue, string timeValue)
    {
        System.DateTime retVal = System.DateTime.MinValue;
        if (Date_TryParseEx(dateValue, ref retVal))
        {
            return Time_ParseEx(retVal, timeValue);
        }
        else
        {
            return retVal;
        }
    }

    public static System.DateTime Time_ParseEx(System.DateTime dateValue, string timeValue)
    {
        System.DateTime retVal = System.DateTime.MinValue;
        if (timeValue != null)
            timeValue = timeValue.Trim();
        if (string.IsNullOrEmpty(timeValue))
            return retVal;
        while (timeValue.EndsWith("+"))
        {
            timeValue = timeValue.Substring(0, timeValue.Length - 1);
            dateValue = dateValue.AddDays(1);
        }
        while (timeValue.EndsWith("-"))
        {
            timeValue = timeValue.Substring(0, timeValue.Length - 1);
            dateValue = dateValue.AddDays(-1);
        }
        Time_FixString(ref timeValue);
        if (Date_TryParseEx(timeValue, ref retVal))
        {
            retVal = dateValue.Date.AddHours(retVal.Hour).AddMinutes(retVal.Minute);
        }
        return retVal;
    }

    public static string Time_ToStringEx(System.DateTime dateValue, System.DateTime timeValue)
    {
        string retVal = null;
        if (Null.IsNull(timeValue))
        {
            retVal = "";
        }
        else
        {
            retVal = timeValue.ToString(CS_DISPLAY_TIME_FORMAT);
            if (timeValue.Date > dateValue.Date)
            {
                retVal += "".PadRight(Convert.ToInt32((timeValue.Date - dateValue.Date).TotalDays), '+');
            }
            else if (timeValue.Date < dateValue.Date)
            {
                retVal += "".PadRight(Convert.ToInt32((dateValue.Date - timeValue.Date).TotalDays), '-');
            }
        }
        return retVal;
    }

    public static System.DateTime Date_ParseEx(string sValue, string sFormat)
    {
        System.DateTime mDate = default(System.DateTime);
        if (System.DateTime.TryParseExact(sValue, sFormat, System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.AdjustToUniversal, out mDate))
        {
            return mDate;
        }
        else
        {
            return Null.NullDate;
        }
    }

    private static System.DateTime Date_ParseEx(string sValue)
    {
        System.DateTime mDate = default(System.DateTime);
        if (Date_TryParseEx(sValue, ref mDate))
        {
            return mDate;
        }
        else
        {
            if (System.DateTime.TryParse(sValue, out mDate))
            {
                return mDate;
            }
            else
            {
                return Null.NullDate;
            }
        }
    }

    public static List<T> List_Clone<T>(List<T> originList) where T : ICloneable
    {
        return originList.Select(i => (T)i.Clone()).ToList();
    }

    public static decimal Decimal_Round(decimal dValue, decimal dRound)
    {
        decimal dDivide = (1 / dRound);
        //0.05
        decimal retVal = Math.Round(dValue * dDivide) / dDivide;
        if (retVal < dValue)
            retVal += dRound;
        return retVal;
    }

    public static bool IsDate(ref string sValue)
    {
        throw new NotImplementedException();
    }



    public static bool IsDBNull(object p)
    {
        return p == DBNull.Value;
    }

    internal static int UBound(Process[] prc)
    {
        throw new NotImplementedException();
    }


    //
    public static bool IsNumber(this object value)
    {
        return value is sbyte
                || value is byte
                || value is short
                || value is ushort
                || value is int
                || value is uint
                || value is long
                || value is ulong
                || value is float
                || value is double
                || value is decimal;
    }

    //Convert chuỗi có dấu sang ko dấu
    public static string String_GetUnsign(string s)
    {
        string stFormD = s.Normalize(NormalizationForm.FormD);
        StringBuilder sb = new StringBuilder();
        for (int ich = 0; ich < stFormD.Length; ich++)
        {
            System.Globalization.UnicodeCategory uc = System.Globalization.CharUnicodeInfo.GetUnicodeCategory(stFormD[ich]);
            if (uc != System.Globalization.UnicodeCategory.NonSpacingMark)
            {
                sb.Append(stFormD[ich]);
            }
        }
        sb = sb.Replace('Đ', 'D');
        sb = sb.Replace('đ', 'd');
        return (sb.ToString().Normalize(NormalizationForm.FormD));
    }

    public static int DateTime_MonthDiff(DateTime lValue, DateTime rValue)
    {
        return Math.Abs((lValue.Month - rValue.Month) + 12 * (lValue.Year - rValue.Year));
    }

    
}



